package server;

import catalina.Context;
import catalina.Mapper;
import catalina.StandardContext;
import catalina.StandardWrapper;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import server.base.HttpServlet;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.List;

/**
 * @ClassName WebAppsParse
 * @Description TODO
 * @Auth ying.xiao
 * @Date 2021/3/11
 * @Version 1.0.0
 */
public class WebAppsParse {

    /**
     * 解析webapp下的项目
     * @param path
     */
    public void parse(Mapper.MappedContext mappedContext, String path) throws Exception {
        StandardContext standardContext = (StandardContext) mappedContext.object;
        File clazzPath = new File(path + "/"+standardContext.getDocBase());
        path = path + "/"+standardContext.getDocBase()+"/"+"web.xml";
        File file = new File(path);
        if(!file.exists()){
            throw new RuntimeException("无效路径"+path);
        }

        //路径加载到类加载器中
        addPathToClassLoader(clazzPath);
        try{
            InputStream inputStream = new FileInputStream(file);
            SAXReader saxReader = new SAXReader();
            Document read = saxReader.read(inputStream);
            //获取跟节点 server
            Element rootElement = read.getRootElement();
            List<Element> servletNodes = rootElement.selectNodes("./servlet");
            for (Element servletNode : servletNodes) {
                Element node = (Element) servletNode.selectSingleNode("servlet-class");
                String servletClass = node.getStringValue();
                Element nodeName = (Element) servletNode.selectSingleNode("servlet-name");
                String servletName = nodeName.getStringValue();

                // 根据servlet-name的值找到url-pattern
                Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                Element url = (Element) servletMapping.selectSingleNode("url-pattern");
                mappedContext.addWrapper(url.getStringValue(),(HttpServlet) Class.forName(servletClass).newInstance());
            }
        }catch (Exception e){
            throw e;
        }
    }

    private void addPathToClassLoader(File clazzPath) throws NoSuchMethodException {
        Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
        boolean accessible = method.isAccessible();
        try {
            if (!accessible) {
                method.setAccessible(true);
            }
            // 设置类加载器
            URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
            // 将当前类路径加入到类加载器中
            method.invoke(classLoader, clazzPath.toURI().toURL());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            method.setAccessible(accessible);
        }
    }
}
